package sharetime.playlist.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import sharetime.core.service.BaseManager;
import sharetime.playlist.domain.Playlist;
import sharetime.playlist.domain.PlaylistResource;
import sharetime.playlist.domain.Resource;
import sharetime.user.domain.UserData;

@Service("playlistManager")
public class DefaultPlaylistManager extends BaseManager implements
		IPlaylistManager {
	private Logger logger = LoggerFactory
			.getLogger(DefaultPlaylistManager.class);

	public static final double OWNER_BONUS = 5.0;
	public static final double RESOURCE_BONUS = 10.0;
	public static final double DERIVATIVE_MULTIPLE = 30;
	public static final double VIEW_MULTIPLE = 0.2;
	public static final double TOP_SCORE_LOG = 10;
	public static final double HIGHEST_RATING = 5;
	public static final float MAX_ITEMS = 1000000;

	@Override
	public Playlist getPlaylistById(long id) {
		return dao.getInstanceById(Playlist.class, id);
	}

	@Override
	public void removePlaylist(long id) {
		logger.debug("entering removePlaylist method");
		dao.remove(getPlaylistById(id));
	}

	@Override
	public void createPlaylist(Playlist playlist) {
		dao.create(playlist);
	}

	@Override
	public void updatePlaylist(Playlist playlist) {
		dao.update(playlist);
	}

	@Override
	public Playlist copyPlaylist(Playlist oldPlaylist, UserData owner) {
		Playlist newPlaylist = new Playlist();

		newPlaylist.setName(owner.getUsername() + "'s version of "
				+ oldPlaylist.getName());
		newPlaylist.setCreationDate(new Date());
		newPlaylist.setLastModificationDate(new Date());
		newPlaylist.setHidden(true);
		newPlaylist.setOwner(owner);
		newPlaylist.setSource(oldPlaylist);

		dao.save(newPlaylist);

		return newPlaylist;
	}

	@Override
	public List<Playlist> getHiddenPlaylist(long userId) {
		String[] params = { "userId" };
		Object[] values = { userId };

		return dao.getInstancesByNamedQueryAndNamedParam(Playlist.class,
				"findHiddenPlaylist", params, values);
	}

	@Override
	public List<Playlist> getUnHiddenPlaylist(long userId) {
		String[] params = { "userId" };
		Object[] values = { userId };

		return dao.getInstancesByNamedQueryAndNamedParam(Playlist.class,
				"findUnHiddenPlaylist", params, values);
	}

	@Override
	public ArrayList<Resource> getUniqueResources(Collection<Playlist> playlists) {
		ArrayList<Resource> uniqueResources = new ArrayList<Resource>();
		for (Playlist p : playlists) {
			for (PlaylistResource pr : p.getPlaylistsResources()) {
				if (!uniqueResources.contains(pr))
					uniqueResources.add(pr);
			}
		}
		return uniqueResources;
	}

	@Override
	public void recomputeScore(long id) {
		Playlist pl = getPlaylistById(id);
		double score = 0;
		int prCount = pl.getPlaylistsResources().size();
		score += prCount > 0 ? RESOURCE_BONUS : 0;

		score += (double) pl.getDerivativeCount() * DERIVATIVE_MULTIPLE;
		score += (double) pl.getViewCount() * VIEW_MULTIPLE;

		pl.setScore(score);
		
		updatePlaylist(pl);
	}

	@Override
	public void incrementViewCount(int id) {
		Playlist pl = getPlaylistById(id);
		pl.setViewCount(pl.getViewCount() + 1);
		recomputeScore(pl.getId());
	}

}
